package com.hfzy.ihk.web.linkcall.support.tts;

import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriber;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberListener;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberResponse;
import com.aliyuncs.exceptions.ClientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.concurrent.*;

public class SpeechTranscriberMultiThread {
    private static final Logger logger = LoggerFactory.getLogger(SpeechTranscriberMultiThread.class);
    private static final String akId = "LTAIJhUHH53zKdJC";
    private static final String akSecrete = "Stv0N02mRpDwD5jiAPYwltG6hCK3aJ";
    private static final String appKey ="Scwu7gKEp1Q63iuq";
    private static String result = "";
    private static SpeechTranscriberListener getTranscriberListener(final String inputName) {

        SpeechTranscriberListener listener = new SpeechTranscriberListener() {
            // 识别出中间结果.服务端识别出一个字或词时会返回此消息.仅当setEnableIntermediateResult(true)时,才会有此类消息返回
            @Override
            public void onTranscriptionResultChange(SpeechTranscriberResponse response) {
                System.out.println("onTranscriptionResultChange: " + inputName +
                        ", name: " + response.getName() +
                        // 状态码 20000000 表示正常识别
                        ", status: " + response.getStatus() +
                        // 句子编号，从1开始递增
                        ", index: " + response.getTransSentenceIndex() +
                        // 当前句子的中间识别结果
                        ", result: " + response.getTransSentenceText() +
                        // 当前已处理的音频时长，单位是毫秒
                        ", time: " + response.getTransSentenceTime());
            }
            // 识别出一句话.服务端会智能断句,当识别到一句话结束时会返回此消息
            @Override
            public void onSentenceEnd(SpeechTranscriberResponse response) {
                System.out.println("onSentenceEnd: " + inputName +
                        ", name: " + response.getName() +
                        // 状态码 20000000 表示正常识别
                        ", status: " + response.getStatus() +
                        // 句子编号，从1开始递增
                        ", index: " + response.getTransSentenceIndex() +
                        // 当前句子的完整识别结果
                        ", result: " + response.getTransSentenceText() +
                        // 当前已处理的音频时长，单位是毫秒
                        ", time: " + response.getTransSentenceTime());
                //有识别的结果时才会 有此结果返回
                result = response.getTransSentenceText();
                logger.info("input stream: " + inputName +
                        ", name: " + response.getName() +
                        // 状态码 20000000 表示正常识别
                        ", status: " + response.getStatus() +
                        // 句子编号，从1开始递增
                        ", index: " + response.getTransSentenceIndex() +
                        // 当前句子的完整识别结果
                        ", result: " + response.getTransSentenceText() +
                        // 当前已处理的音频时长，单位是毫秒
                        ", time: " + response.getTransSentenceTime());
            }
            // 识别完毕
            @Override
            public void onTranscriptionComplete(SpeechTranscriberResponse response) {
                System.out.println("input stream: " + inputName +
                        ", name: " + response.getName() +
                        ", status: " + response.getStatus());
            }
        };
        return listener;
    }



    public Boolean task(String appKey,NlsClient client,String audioFile) throws Exception {
        SpeechTranscriber transcriber = null;
        try {
            File file = new File(audioFile);
            String audioFileName = file.getName();
            SpeechTranscriberListener listener = getTranscriberListener(audioFileName);
            // Step1 创建实例,建立连接
            transcriber = new SpeechTranscriber(client, listener);
            transcriber.setAppKey(appKey);
            // 输入音频编码方式
            transcriber.setFormat(InputFormatEnum.PCM);
            // 输入音频采样率
            transcriber.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
            // 是否返回中间识别结果
            transcriber.setEnableIntermediateResult(false);
            // 是否生成并返回标点符号
            transcriber.setEnablePunctuation(true);
            // 是否将返回结果规整化,比如将一百返回为100
            transcriber.setEnableITN(false);
            // Step2 此方法将以上参数设置序列化为json发送给服务端,并等待服务端确认
            transcriber.start();
            // Step3 语音数据来自声音文件用此方法,控制发送速率;若语音来自实时录音,不需控制发送速率直接调用 recognizer.sent(ins)即可
            InputStream ins = new FileInputStream(file);
            transcriber.send(ins, 6400, 200);
            // Step4 通知服务端语音数据发送完毕,等待服务端处理完成
            transcriber.stop();
            System.out.println("====================");
            return true;

        } catch (Exception e) {
            System.err.println(e.getMessage());
        } finally {
            // Step5 关闭连接
            if (null != transcriber) {
                transcriber.close();
            }
        }
        return  false;
    }

    /**
     * @param  audioFile 音频文件
     * */
    public String doSpeechToText(ExecutorService executorService, String audioFile){
        logger.info("doSpeechToText 识别语音文件：{}",audioFile);
        try {
            result = "";//重置该result 值
            String token = CreateToken.aliyunToken(akId,akSecrete); //这个启用项目用
//        AccessToken accessToken = AccessToken.apply("LTAIJhUHH53zKdJC", "Stv0N02mRpDwD5jiAPYwltG6hCK3aJ");
//        String token = accessToken.getToken();
//        String token= "9bd74d7e116043159490d5a38e8a6bbb";//测试用

//        String audioFile = "D:\\recordFile\\OUT\\mp3\\20181023\\1.pcm";
            final NlsClient client = new NlsClient(token);
            Future<Boolean> future = executorService.submit(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return  task(appKey, client, audioFile);
                }
            });
            if(future.get()){
                logger.info("doSpeechToText 识别结果：{}",result);
                System.out.println("result==="+result);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return result;
    }
}
